// ========================================================================
// 统一查询保存 Restfull API 列表
// ========================================================================

import axios from 'axios'
import request from '@/utils/request'
import { parseTime } from '@/utils/index'
import Layout from '@/layout'

// 独立Bean
// const alone_beans = ['user', 'order', 'goods', 'acct']
// 获取单个
function getModuleUrl(beanName) {
  return process.env.VUE_APP_MODULE_BAS
}

export default {
  getListData(that, after) {
    const tmp = filterParams(that.getData)
    that.listData.loading = true
    this.getListPage(that.bean, tmp).then(res => {
      that.listData.data = res.data
      that.listData.total = res.total
      that.listData.loading = false
      that.loadings = []
      after && after(res.data)
    })
  },
  cmStatus(that, scope, status, title) {
    this.confirm(that, { scope: scope, status: status, title: title }).then(data => {
      this.doStatus(that, data.scope, data.status, data.title)
    })
  },
  doStatus(that, scope, status, title) {
    that.$set(that.$data.loadings, scope.$index, true)
    this.saveData(that, { id: scope.row.id, status: status }, title)
  },
  saveEvts(that, formData, title, ref = 'formData') {
    that.$refs[ref].validate(valid => {
      if (valid) {
        this.saveData(that, !formData ? that.$data.formData : formData, !title ? that.$data.popData.button : title)
      } else {
        return false
      }
    })
  },
  saveData(that, data, title) {
    that.$data.popData.loading = true
    this.saveOne(that.$data.bean, data).then(res => {
      this.success(that, title).then(that => {
        that.$data.popData.show = false
        that.$data.popData.loading = false
        this.getListData(that.$data)
      })
    }).catch(() => {
      that.$data.loadings = []
      that.$data.popData.loading = false
    })
  },
  onAdd(list, val = {}) {
    list.push(val)
  },
  onDel(list, index) {
    list.splice(index, 1)
  },
  onEdit(data, scope) {
    data.popData = {
      show: true,
      title: !scope ? '新增' : '编辑',
      button: !scope ? '新增' : '保存',
      loading: false
    }
    data.formData = JSON.parse(JSON.stringify(scope ? scope.row : data.editForm))
  },
  confirm(that, data) {
    const title = data['title'] ? data['title'] : '操作'
    return new Promise((resolve, reject) => {
      that.$confirm(title + ', 是否继续?', '提示', { type: 'warning' }).then(() => {
        resolve(data)
      }).catch(() => {
        that.$message({
          type: 'info',
          message: '已取消'
        })
      })
    })
  },
  success(that, title = '操作') {
    return new Promise((resolve, reject) => {
      that.$notify({
        title: '成功',
        message: title + '成功',
        type: 'success',
        duration: 1000,
        onClose: () => {
          resolve(that)
        }
      })
    })
  },
  // 获取单个
  getOne(beanName, id, showFlags = '') {
    return this.getListPage(beanName, { pageNum: 1, pageSize: 1, showFlags: showFlags, params: { id: id }})
  },
  // 获取分页列表
  getListPage(beanName, data) {
    return newReq(beanName, 'listPageBy', data, 'post')
  },
  // 根据nextId获取列表
  offsetBy(beanName, data) {
    return newReq(beanName, 'offsetBy', data, 'post')
  },
  // 单个添加或更新
  saveOne(beanName, data) {
    return this.saveBatch(beanName, [data])
  },
  // 批量添加或更新
  saveBatch(beanName, data) {
    const clears = ['creator', 'createTime', 'updator', 'updateTime', 'statusText', 'version']
    for (const d of data) {
      clearObject(d, clears)
    }
    console.log('saveBatch.data', JSON.stringify(data))
    return newReq(beanName, 'saveBatch', data, 'post')
  },
  // 新自定义请求
  newRequest(beanName, func, data, method = 'post', options = {}) {
    return newReq(beanName, func, data, method, options)
  },
  saveChanges(that, changes, title = '保存排序') {
    that.popData.loading = true
    this.saveBatch(that.bean, changes).then(res => {
      this.success(that, title).then(that => {
        that.changes = []
        that.popData.show = false
        that.popData.loading = false
        that.getListData(that.$data)
      })
    }).catch(() => {
      that.loadings = []
      that.popData.loading = false
    })
  },
  getOrderNo(dataList, row) {
    return row && row.childList && row.childList.length ? row.childList.length : (dataList && dataList.length ? dataList.length : 0) + 1
  },
  getOrderBy(dataList, row) {
    return row && row.childList && row.childList.length ? row.childList.length : (dataList && dataList.length ? dataList.length : 0) + 1
  },
  onUp(that, dataList, changes, row, prop) {
    const list = getList(dataList, row)
    const index = getIndex(list, row)
    if (index > 0) {
      const temp = JSON.parse(JSON.stringify(list[index]))
      that.$set(list, index, list[index - 1])
      that.$set(list, index - 1, temp)
      that.$set(list[index], prop, index + 1)
      that.$set(list[index - 1], prop, index)
      onChange(changes, list[index], prop)
      onChange(changes, list[index - 1], prop)
    }
  },
  onDown(that, dataList, changes, row, prop) {
    console.log('dataList', dataList, changes, row, prop)
    const list = getList(dataList, row)
    const index = getIndex(list, row)
    if (index < list.length - 1) {
      const temp = JSON.parse(JSON.stringify(list[index]))
      that.$set(list, index, list[index + 1])
      that.$set(list, index + 1, temp)
      that.$set(list[index], prop, index + 1)
      that.$set(list[index + 1], prop, index + 2)
      onChange(changes, list[index], prop)
      onChange(changes, list[index + 1], prop)
    }
  }
}
// ========================================================================
// 新自定义请求
function newReq(beanName, func, data, method = 'post', options = {}) {
  method = method.toLowerCase()
  let url = getModuleUrl(beanName)
  if ((func === 'listPageBy' && method === 'post') || (func === 'offsetBy' && method === 'post') ||
    (func === 'saveBatch' && method === 'post') || (func === 'deleteBatch' && method === 'post')) {
    url += '/api/v6/' + func + '/' + beanName + '/'
  } else {
    url += '/api/' + beanName + '/' + func + '/'
  }
  return request({ url: url, method: method, data: data })
}
// 单个删除
export function delOne(beanName, id) {
  return delBatch(beanName, [id])
}
// 批量删除
export function delBatch(beanName, ids) {
  return this.newRequest(beanName, 'deleteBatch', ids, 'post')
}

// 循环分页不断读取数据
export function loadData(loadFunc, bean, pageSize, getData, data = {}, filterFun, next = false) {
  return new Promise((resolve, reject) => {
    if (!next) {
      data.show = false
      data.loading = true
      data.params = filterParams(getData)
      data._button = data.button
      data._list = []
    }
    data.params.pageSize = pageSize
    data.params.pageNum = data.params.pageNum || 1
    data.button = '加载数据中...' + data.params.pageNum + (data.pages ? ('/' + data.pages) : '')
    loadFunc(bean, data.params).then(res => {
      data.pages = data.pages || parseInt((res.total + pageSize - 1) / pageSize)
      data._list = data._list.concat(filterFun ? filterFun(res.data) : res.data)
      if (data.params.pageNum >= data.pages) {
        data.show = true
        data.loading = false
        data.button = data._button // '加载数据完成' + data.params.pageNum + '/' + data.pages
        console.log('加载数据完成', data._list.length)
        resolve(data._list)
      } else {
        data.params.pageNum++
        data.params.nextId = res.data ? res.data[res.data.length - 1][res.idName] : 0
        loadData(loadFunc, bean, pageSize, getData, data, filterFun, true).then(data => {
          resolve(data)
        })
      }
    })
  })
}

// Excel循环分页不断读取数据且导出数据
export async function exportLoad(loadFunc, bean, fileName, pageSize, getData, showData, excelData, filterFun) {
  showData.button = 'Excel正在准备...'
  console.log('excelData', excelData)
  if (!excelData.header && !excelData.filter) {
    const header = []
    const filter = []
    for (const prop in excelData) {
      header.push(prop)
      filter.push(excelData[prop])
    }
    excelData['header'] = header
    excelData['filter'] = filter
  }
  excelData.name = fileName
  // eslint-disable-next-line require-atomic-updates
  excelData.list = (await loadData(loadFunc, bean, pageSize, getData, showData, filterFun))
  // filterFun && filterFun(excelData.list) => loadData 中使用，减少最后结果list数据量太大问题
  // console.log('excelData.list', JSON.stringify(excelData.list))
  exportExcel(excelData, () => {
    showData.loading = false
    showData.button = '导出'
  })
}

export function exportExcel(data, callback) {
  import('@/vendor/Export2Excel').then(excel => {
    excel.export_json_to_excel({
      header: data.header,
      data: formatJson(data.filter, data.list),
      filename: data.name + '_' + parseTime(new Date()),
      autoWidth: true,
      bookType: 'xlsx'
    })
    callback && callback()
  })
}

export function formatJson(filterVal, jsonData) {
  return jsonData.map(v => filterVal.map(j => {
    return getByJson(v, j)
  }))
}

export function getByJson(json, prop) {
  if (prop.indexOf('[') > 0 && prop.indexOf(']') > 0) {
    const tmp = json[prop.substring(0, prop.indexOf('['))][prop.substring(prop.indexOf('[') + 1, prop.indexOf(']'))]
    if (tmp) {
      if (prop.indexOf('.') > 0) {
        return getByJson(tmp, prop.substring(prop.indexOf('.') + 1))
      } else {
        return tmp
      }
    } else {
      return json[prop]
    }
  } else if (prop.indexOf('.') > 0) {
    if (json[prop.substring(0, prop.indexOf('.'))]) {
      return getByJson(json[prop.substring(0, prop.indexOf('.'))], prop.substring(prop.indexOf('.') + 1))
    } else {
      return json[prop]
    }
  } else if (prop.endsWith('Time') && json[prop]) {
    return parseTime(json[prop])
  } else if (prop.startsWith('#') && prop.endsWith('#')) {
    return prop
  } else {
    return json[prop]
  }
}

/**
 * 清理无效的属性值
 */
export function clearObject(data, clears = [], level = 0) {
  level++
  for (const clear of clears) {
    if (data[clear]) {
      delete data[clear]
    }
  }
  for (const prop in data) {
    if (data[prop] === null) {
      delete data[prop]
    } else if (typeof data[prop] === 'object') {
      if (level === 1) {
        if (data[prop] instanceof Array) {
          for (const arrData of data[prop]) {
            if (arrData !== null && typeof arrData === 'object') {
              clearObject(arrData, clears, level)
            }
          }
        } else {
          clearObject(data[prop], clears, level)
        }
      }
    }
  }
}

export function filterParams(data = {}) {
  const tempData = JSON.parse(JSON.stringify(data))
  if (tempData.params && tempData.params.status === 'A') {
    delete tempData.params.status
  }
  for (const prop in tempData) {
    if (prop.endsWith('Array')) {
      if (tempData[prop] && tempData[prop].length && tempData[prop].length === 2) {
        tempData.params[prop.replace('Array', '$Gt')] = tempData[prop][0]
        tempData.params[prop.replace('Array', '$Lt')] = tempData[prop][1]
      } else {
        delete tempData.params[prop.replace('Array', '$Gt')]
        delete tempData.params[prop.replace('Array', '$Lt')]
      }
      delete tempData[prop]
    }
  }
  return tempData
}

export function getUploadUrl(local) {
  if (local) {
    return process.env.VUE_APP_BASE_API + '/' + process.env.VUE_APP_MODULE_BAS + 'api/v6/uploadLocal/'
  } else {
    return process.env.VUE_APP_BASE_API + '/' + process.env.VUE_APP_MODULE_BAS + 'api/v6/upload/'
  }
}

export function isAdmin() {
  const name = sessionStorage.getItem('name')
  return name && (name === '13800000001' || name === '13800000002')
}

export function getClientId() {
  return sessionStorage.getItem('clientId')
}

/**
 * 下载文件
 * @param {*} bean 类
 * @param {*} func 方法
 * @param {*} data 传入对象
 * @param {*} fileName 文件名
 * @param {*} postfix 后缀
 */
export function onDownload(bean, func, data, fileName, postfix = 'xlsx') {
  console.log('data', bean, func, JSON.stringify(data), fileName, postfix)
  return new Promise((resolve, reject) => {
    // instance
    const instance = axios.create({
      baseURL: process.env.VUE_APP_BASE_API,
      timeout: 30000,
      headers: {
        'Token': sessionStorage.getItem('token')
      },
      responseType: 'blob'
    })
    instance.post('/api/' + bean + '/' + func + '/', data).then(res => {
      const data = res.data
      const time = parseTime(new Date().getTime()).replaceAll(/[- :]/gi, '')
      fileName += '_' + time + '_' + new Date().getMilliseconds() + '.' + postfix
      if (window.navigator && window.navigator.msSaveOrOpenBlob) {
        const blob = new Blob([data], { type: 'application/vnd.ms-excel' })
        window.navigator.msSaveOrOpenBlob(blob, fileName)
      } else {
        /* 火狐谷歌的文件下载方式 */
        const blob = new Blob([data])
        var downloadElement = document.createElement('a')
        var href = window.URL.createObjectURL(blob)
        downloadElement.href = href
        downloadElement.download = fileName
        document.body.appendChild(downloadElement)
        downloadElement.click()
        document.body.removeChild(downloadElement)
        window.URL.revokeObjectURL(href)
      }
      resolve(res.data)
    }).catch((error) => {
      console.log(error)
      reject(error)
    })
  })
}

/**
 * 递归接口返回菜单列表，返回用户可见左导航
 * @param menus 用户拥有的左导航
 */
export function formatRoutes(menus) {
  const res = []
  menus.forEach(menu => {
    let isHidden = false
    if (menu.hide !== undefined && menu.hide !== null && menu.hide) {
      isHidden = true
    }
    if (menu.parentId === '' && menu.compt !== 'Layout' && (menu.childList === undefined || menu.childList === null)) {
      res.push({
        path: menu.router,
        component: Layout,
        children: [{
          path: 'index',
          name: menu.router,
          // component: () => import('@/views/' + menu.compt),
          component: resolve => require(['@/views/' + menu.compt + '.vue'], resolve),
          meta: { title: menu.name, icon: menu.icon }
        }],
        hidden: isHidden
      })
    } else {
      res.push({
        path: menu.router,
        name: menu.router,
        component: menu.compt === 'Layout' ? Layout : resolve => require(['@/views/' + menu.compt + '.vue'], resolve),
        children: menu.childList === undefined || menu.childList === null ? [] : formatRoutes(menu.childList),
        meta: { title: menu.name, icon: menu.icon, url: menu.url }, //
        hidden: isHidden
      })
    }
  })
  return res
}

function onChange(changes, data, prop) {
  const find = changes.find(v => v.id === data.id)
  if (find) {
    find[prop] = data[prop]
  } else {
    changes.push({ id: data.id, prop: data[prop] })
  }
}
function getList(dataList, row) {
  console.log('getList', dataList, row)
  if (!dataList) return []
  if (!row.parentId || row.parentId === 0) return dataList
  const find = dataList.find(v => v.id === row.parentId)
  return find ? find.childList : []
}
function getIndex(list, row) {
  return !list ? 0 : list.findIndex(v => v.id === row.id)
}
